#include <windows.h>
#include <stdlib.h>
#include <ctype.h>

#include "sha2.h"
#include "CryptManager.h"

CryptManager::CryptManager() {
	DWORD index;

	/* generate a table for a byte-wise 32-bit CRC calculation on the polynomial: 0xEDB88320 */
	index = 0UL;
	do {
		DWORD index2, value;

		value = index;
		index2 = 8;
		do {
			if (value & 1) {
				value = (value >> 1) ^ 0xEDB88320;
			}
			else {
				value = value >> 1;
			}
			--index2;
		}
		while (index2);
		table[index++] = value;
	}
	while (index < 256);
}

CryptManager::~CryptManager() {
	// nothing to do
}

void CryptManager::ClientPassHash(char* username, char* password, unsigned char* digest) {
	DWORD username_len, password_len;

	char buffer[31];

	ZeroMemory(buffer, 31);

	username_len = strlen(username);
	password_len = strlen(password);

	/* limit password string to max 30 characters */
	if (password_len > 30) {
		password_len = 30;
	}

	memcpy(buffer, password, password_len);

	// append '*' as delimiter after password
	if (password_len < 30)
		*(char*) (password_len++ + buffer) = '*';
	// fill up unused buffer with the username string
	if (username_len && password_len < 30) {
		do {
			*(char*) (password_len + buffer) = tolower(username[password_len % username_len]);
			++password_len;
		}
		while (password_len < 30);
	}

	// get hash
	sha256((const unsigned char*) buffer, 30, digest);
}

DWORD CryptManager::Crc32(BYTE* buf, DWORD len) {
	DWORD ret_val;

	ret_val = 0UL;
	if(len){
		do{
			ret_val = table[((BYTE)ret_val ^ *buf++)] ^ (ret_val >> 8UL) ^ 0xD202EF8DUL;
			--len;
		}while(len);
	}

	return (ret_val);
}
